/*
 * vendedor.cpp
 *
 */
#include "../common/Argv.h"
#include <map>
#include <sstream>
#include "../middleware/CommunicationADP.h"
#include "../middleware/CommunicationAdpt.h"
#include "../middleware/CommunicationVendedor.h"
#include "../logger/logger.h"

int main(int argc, char **argv)
{
	std::string hostName = "vendedor_pc";
	//Toma argumentos (main)
	Argv args(argv);

	//Si se le pasa un argumento tomarlo como hostname
	if (args.getArgc() == 2)
		hostName = args.getArg(1);


	middleware::CommunicationVendedor communicationVendedor(hostName);
	middleware::CommunicationADP communicationADP(hostName);

	std::stringstream ss;
	//El primer parametro es el clientId
	std::map<int, ProductoCantidadList> pedidosCliente;

	int vendedorId;
	vendedorId = communicationVendedor.generateVendedorId();

	CLogger::create("Vendedor "+StringUtils::NumberToString(vendedorId));
	CLogger::setLevel(LogLevelEnum::TRACE);

	CLogger::log("Vendedor started", LogLevelEnum::INFO);

	middleware::CommunicationAdpt::launchForVendedor(hostName,vendedorId);
	middleware::CommunicationAdpt communicationAdpt(hostName);

	communicationVendedor.avisarVendedorDisponible(vendedorId);

	while(true)
	{
		int clientId;
		OrdenCompraHeader ordenCompra;
		bool isOrdenCompraEnded;
		ProductoCantidad producto;

		communicationVendedor.receiveOrdenCompra(vendedorId,clientId,
										producto,ordenCompra,
										isOrdenCompraEnded);

		if(!isOrdenCompraEnded)
		{
			pedidosCliente[clientId].push_back(producto);
			ss.str("");
			ss << "Pedido item:"<< producto.tipo<< " cantidad:"<< producto.tipo;
			CLogger::log(ss.str(), LogLevelEnum::TRACE);
		}
		else
		{
			ProductoCantidadList productosEnStock;
			ProductoCantidadMap cantidadesMinimas;
			ProductoCantidadList cantidadesPedido = pedidosCliente[clientId];
			std::map<int, ProductoCantidadList>::iterator it;
			ss.str("");
			ss << "Se recibio fin de pedido para cliente:"<< clientId<<
				  " con orden compra:"<< ordenCompra.ordenCompraId;
			CLogger::log(ss.str(), LogLevelEnum::TRACE);

			//TODO obtener cantidades minimas a producir
			if(!communicationAdpt.reservarProductos(ordenCompra,
													cantidadesPedido,
												    productosEnStock,
												    cantidadesMinimas))
			{
				CLogger::log("No habia espacio para el pedido del cliente", LogLevelEnum::ERROR);
				communicationVendedor.respondOrdenCompra(clientId,middleware::CommunicationVendedor::OC_ERROR_NO_HAY_ESPACIO);
				CLogger::log("Vendedor disponible", LogLevelEnum::INFO);
				communicationVendedor.avisarVendedorDisponible(vendedorId);
				continue;
			}
			else
			{
				ProductoCantidadList::iterator itProdCantidad;
				ProductoCantidadList::iterator itProdStock;

				for(itProdCantidad = cantidadesPedido.begin();
					itProdCantidad != cantidadesPedido.end();
					itProdCantidad++)
				{

					for(itProdStock = productosEnStock.begin();
							itProdStock != productosEnStock.end();
							itProdStock++)
					{
						if(itProdStock->tipo == itProdCantidad->tipo)
						{
							if(itProdStock->cantidad <itProdCantidad->cantidad)
							{
								ProductoCantidad pedidoProducir;

								pedidoProducir.tipo = itProdStock->tipo;
								pedidoProducir.cantidad = itProdCantidad->cantidad -itProdStock->cantidad;


								ss.str("");
								ss << "Se mandan a producir:"<< pedidoProducir.cantidad
								   << " productos de tipo:"<<pedidoProducir.tipo;

								CLogger::log(ss.str(), LogLevelEnum::TRACE);
								communicationADP.producir(pedidoProducir);
							}

							break;
						}
					}
				}

				ss.str("");
				ss << "Se avisa al cliente:"<< clientId
				   << " que se termino su orden de compra con id Orden compra:"
				   <<ordenCompra.ordenCompraId;

				CLogger::log(ss.str(), LogLevelEnum::TRACE);

				communicationVendedor.respondOrdenCompra(clientId,middleware::CommunicationVendedor::OC_OK);
			}

			//Saco los elementos de las ordenes de compra actuales
			it = pedidosCliente.find(clientId);
			pedidosCliente.erase(it);

			CLogger::log("Vendedor disponible", LogLevelEnum::INFO);
			communicationVendedor.avisarVendedorDisponible(vendedorId);
		}
	}

	return 0;
}
